package com.wyclabs.auth.common.exception;

import com.wyclabs.commons.constants.ErrorCodes;
import com.wyclabs.commons.constants.LoginErrorCodes;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.security.oauth2.common.exceptions.InvalidScopeException;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.common.exceptions.UnsupportedGrantTypeException;
import org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator;
import org.springframework.web.HttpRequestMethodNotSupportedException;

import java.util.HashMap;
import java.util.Map;

/**
 * 错误信息转换
 * @author sr
 * @date 2019/10/17
 */
public class SecurityExceptionTranslator extends DefaultWebResponseExceptionTranslator {

    private static final Map<String, String> ERROR_MAP = new HashMap<>(9);

    static {
        ERROR_MAP.put("Bad credentials", "用户名或密码错误");
        ERROR_MAP.put("坏的凭证", "用户名或密码错误");
        ERROR_MAP.put("User credentials have expired", "用户认证已过期");
        ERROR_MAP.put("User is disabled", "账号不可用");
        ERROR_MAP.put("用户已失效", "账号已停用");
        ERROR_MAP.put("User account has expired", "账号已过期");
        ERROR_MAP.put("User account is locked", "账号已被锁定");
        ERROR_MAP.put("Empty username not allowed", "手机号不能为空");
        ERROR_MAP.put("Only UsernamePasswordAuthenticationToken is supported", "仅支持用户名密码类型");
    }

    private Logger logger = LoggerFactory.getLogger(SecurityExceptionTranslator.class);

    /**
     * @param e spring security内部异常
     * @return 经过处理的异常信息
     * @throws Exception 通用异常
     */
    @Override
    public ResponseEntity<OAuth2Exception> translate(Exception e) throws Exception {
        OAuth2Exception oAuth2Exception = null;
        if (e instanceof InvalidGrantException) {
            String msg = ERROR_MAP.get(e.getMessage());
            if (StringUtils.isNotBlank(msg)) {
                oAuth2Exception = new CustomOauth2Exception(LoginErrorCodes.INVALID_GRANT.getCode(), msg);
            }
            String invalidRefreshToken = "Invalid refresh token";
            if (e.getMessage().contains(invalidRefreshToken)) {
                oAuth2Exception = new CustomOauth2Exception(LoginErrorCodes.INVALID_REFRESH_TOKEN.getCode(), LoginErrorCodes.INVALID_REFRESH_TOKEN.getDescription());
            }

        }
        if (e instanceof UnsupportedGrantTypeException) {
            oAuth2Exception = new CustomOauth2Exception(LoginErrorCodes.UNSUPPORTED_GRANT_TYPE.getCode(), LoginErrorCodes.UNSUPPORTED_GRANT_TYPE.getDescription());
        }
        if (e instanceof InternalAuthenticationServiceException) {
            String upmsFaild = "failed and no fallback";
            if (e.getMessage().contains(upmsFaild)) {
                oAuth2Exception = new CustomOauth2Exception(ErrorCodes.ERROR_SERVER_BUSY.getCode(), ErrorCodes.ERROR_SERVER_BUSY.getDescription());
            } else {
                oAuth2Exception = new CustomOauth2Exception(ErrorCodes.ERROR_SERVER_ERROR.getCode(), e.getMessage());
            }
        }
        if (e instanceof InvalidScopeException) {
            oAuth2Exception = new CustomOauth2Exception(LoginErrorCodes.INVALID_SCOPE.getCode(), LoginErrorCodes.INVALID_SCOPE.getDescription());
        }

        if (e instanceof HttpRequestMethodNotSupportedException) {
            oAuth2Exception = new CustomOauth2Exception(ErrorCodes.ERROR_REQUEST_WRONG.getCode(), ErrorCodes.ERROR_REQUEST_WRONG.getDescription());
        }

        String missingGrantType = "Missing grant type";
        if (e.getMessage().contains(missingGrantType)) {
            oAuth2Exception = new CustomOauth2Exception(LoginErrorCodes.MISSING_GRANT_TYPE.getCode(), LoginErrorCodes.MISSING_GRANT_TYPE.getDescription());
        }
        if (oAuth2Exception != null) {
            return super.translate(oAuth2Exception);
        }
        logger.warn(e.getMessage());
        return super.translate(e);
    }
}
